import { Button, Empty, Form, Input, Modal, notification } from 'antd';

import { BaseNodeProps, NodeDataTypes } from '@/components/complex/BaseNode/define';
import { NODE_TYPE } from '@/constants/config';
import { useGraph } from '@/hooks/useGraph';
import { useNodeResults } from '@/store/node-results';
import { useNodeVerificationResults } from '@/store/node-verification';
import { validateAssignments, validateCriteria } from '@/utils/cells-validator';
import { fetchOfSSE } from '@/utils/fetch-sse';
import { showEdgeStatusWithVerification, showNodeStatusWithState } from '@/utils/graph';

interface ActionsTestProps {
  beforeTest?: () => Promise<void> | undefined;
}

export const ActionsTest = memo<ActionsTestProps>((props) => {
  const { graph } = useGraph();
  const [open, setOpen] = useState(false);
  const [fields, setFields] = useState<VariableItem[]>([]);
  const [form] = Form.useForm();
  const [loading, setLoading] = useState(false);
  const [searchParams] = useSearchParams();
  const flowId = searchParams.get('flowId') as string;
  const { addResults, clearResults } = useNodeResults();
  const verificationResultsStore = useNodeVerificationResults();

  const testHandle = async () => {
    setLoading(true);
    try {
      await props.beforeTest?.();
      setOpen(true);
      const startNode = graph
        ?.getNodes()
        .find((node) => node.shape === NODE_TYPE.START)
        ?.getData<BaseNodeProps<NODE_TYPE.START>>();

      if (!startNode) {
        return;
      }

      setFields(startNode?.publicVariables || []);
    } finally {
      setLoading(false);
    }
  };

  const verification = () => {
    const validResultOk: boolean[] = [];
    graph?.getEdges().forEach((edge) => {
      const criteria = edge.getData()?.data?.criteria;
      const errorMsgList = criteria ? validateCriteria(criteria) : [];
      const success = errorMsgList.length === 0;
      verificationResultsStore.addResults({
        edgeId: edge.id,
        errorMsgList,
        success
      });

      validResultOk.push(success);

      showEdgeStatusWithVerification(graph, {
        edgeId: edge.id,
        status: success ? 'INIT' : 'FAILED',
        labels: errorMsgList
      });
    });

    graph?.getNodes().forEach((node) => {
      const nodeType = node.shape as keyof typeof NODE_TYPE;
      const nodeData = node.toJSON()?.data;
      const nodeId = node.id as unknown as string;
      const errorMsgList: string[] = [];

      if (nodeType === NODE_TYPE.DATA_LOAD) {
        const tempData = nodeData.data as NodeDataTypes[NODE_TYPE.DATA_LOAD];
        if (!tempData?.tableName) {
          errorMsgList.push('数据集不可为空');
        }
        if (!tempData?.columns?.length) {
          errorMsgList.push('查询列不可为空');
        }
        if (!tempData?.criteria) {
          errorMsgList.push('条件不可为空');
        } else {
          const errorList = validateCriteria(tempData.criteria);
          errorMsgList.push(...errorList);
        }
      } else if (nodeType === NODE_TYPE.RULE) {
        const tempData = nodeData.data as NodeDataTypes[NODE_TYPE.RULE];
        if (tempData?.enableListOperator) {
          if (!tempData?.listOperator) {
            errorMsgList.push('集合判断方式不可为空');
          }
        }
        if (!tempData?.rulesList?.length) {
          errorMsgList.push('规则赋值不可为空');
        } else {
          const rules = tempData.rulesList;
          for (let index = 0; index < rules.length; index++) {
            const ruleItem = rules[index];
            if (ruleItem) {
              const criteria = ruleItem.criteria;
              const assignments = ruleItem.assignments;
              errorMsgList.push(...validateCriteria(criteria));
              errorMsgList.push(...validateAssignments(assignments));
            }
          }
        }
      } else if (nodeType === NODE_TYPE.DATA_MODIFY) {
        const tempData = nodeData.data as NodeDataTypes[NODE_TYPE.DATA_MODIFY];
        if (!tempData?.tableName) {
          errorMsgList.push('数据集不可为空');
        }
        if (Object.keys(tempData?.mapping || {}).length === 0) {
          errorMsgList.push('参数映射不可为空');
        } else {
          const keysErrorIndex = Object.keys(tempData?.mapping || {}).findIndex((item) => !item);
          if (keysErrorIndex !== -1) {
            errorMsgList.push(`参数映射第${keysErrorIndex + 1}行数据集字段为空`);
          }
          const valuesErrorIndex = Object.values(tempData?.mapping || {}).findIndex((item) => !item);
          if (valuesErrorIndex !== -1) {
            errorMsgList.push(`参数映射第${keysErrorIndex + 1}行决策流入参为空`);
          }
        }
        errorMsgList.push(...validateCriteria(tempData?.criteria!));
      } else if (nodeType === NODE_TYPE.API) {
        const tempData = nodeData.data as NodeDataTypes[NODE_TYPE.API];
        if (!tempData?.actionId) {
          errorMsgList.push('API配置不可为空');
        }
      }

      const success = errorMsgList.length === 0;
      verificationResultsStore.addResults({
        nodeId,
        errorMsgList,
        success
      });
      validResultOk.push(success);
    });

    const noError = validResultOk.every(Boolean);
    if (noError) {
      verificationResultsStore.clearResults();
    }
    return noError;
  };

  const handleOk = () => {
    form.validateFields().then((data) => {
      verificationResultsStore.clearResults();
      if (verification() === false) {
        setOpen(false);
        setLoading(false);
        notification.error({
          message: '节点验证失败',
          description: '请检查节点配置',
          showProgress: true,
          placement: 'bottomRight'
        });
        return;
      }
      setLoading(true);
      clearResults();
      setOpen(false);
      fetchOfSSE('/flow/test', {
        headers: {
          'Content-Type': 'application/json'
        },
        method: 'POST',
        body: JSON.stringify({
          flowId: Number(flowId),
          param: data
        }),
        onMessage(message) {
          if (message === '[DONE]') {
            setLoading(false);
            return;
          }
          const data = JSON.parse(message);
          addResults(data);
          showNodeStatusWithState(graph!, data);
        }
      }).catch(() => {
        notification.error({
          message: '测试失败',
          placement: 'bottomRight'
        });
        setLoading(false);
      });
    });
  };

  return (
    <>
      <Button loading={loading} type="primary" onClick={testHandle}>
        <span className="i-solar:play-bold"></span>测试
      </Button>
      <Modal
        title="测试"
        confirmLoading={loading}
        open={open}
        onOk={handleOk}
        onCancel={() => {
          setOpen(false);
          setLoading(false);
        }}>
        <Form form={form} layout="vertical">
          {!fields.length && (
            <div className="text-14">
              <Empty description="暂无入参" />
            </div>
          )}
          {fields.map((item) => {
            return (
              <Form.Item
                key={item.varName}
                rules={[
                  {
                    required: true,
                    message: '请输入该项值'
                  }
                ]}
                label={item.varLabel}
                name={item.varName}>
                <Input placeholder="请输入" />
              </Form.Item>
            );
          })}
        </Form>
      </Modal>
    </>
  );
});
